package club.kynb.mall.application.statemachine.order.config;

import club.kynb.mall.application.context.OrderContext;
import club.kynb.mall.application.statemachine.order.action.*;
import club.kynb.mall.application.statemachine.order.codition.*;
import club.kynb.mall.order.constant.OrderEventEnum;
import club.kynb.mall.order.constant.OrderStatusEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pizza.statemachine.StateMachine;
import org.pizza.statemachine.builder.StateMachineBuilder;
import org.pizza.statemachine.builder.StateMachineBuilderFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author kynb_club@163.com
 * @since 2021/7/9 10:00 上午
 */
@Slf4j
@Configuration
@AllArgsConstructor
public class OrderStatemachineConfiguration {
    public static final String ORDER_STATE_MACHINE_ID = "MALL_ORDER_STATE_MACHINE";
    private final OrderCancelCondition orderCancelCondition;
    private final OrderCreateCondition orderCreateCondition;
    private final OrderPreviewCondition orderPreviewCondition;
    private final OrderConfirmCondition orderConfirmCondition;
    private final OrderRefundCondition orderRefundCondition;
    private final OrderRefundCancelCondition orderRefundCancelCondition;

    private final OrderCancelAction orderCancelAction;
    private final OrderCreateAction orderCreateAction;
    private final OrderPreviewAction orderPreviewAction;
    private final OrderConfirmAction orderConfirmAction;
    private final OrderRefundAction orderRefundAction;
    private final OrderRefundCancelAction orderRefundCancelAction;

    @Bean
    public StateMachine<OrderStatusEnum, OrderEventEnum, OrderContext> orderStateMachine() {
        StateMachineBuilder<OrderStatusEnum, OrderEventEnum, OrderContext> builder = StateMachineBuilderFactory.create();
        builder.externalTransition()
                .from(OrderStatusEnum.NONE)
                .to(OrderStatusEnum.INIT)
                .on(OrderEventEnum.PREVIEW)
                .when(orderPreviewCondition)
                .perform(orderPreviewAction);

        builder.externalTransition()
                .from(OrderStatusEnum.INIT)
                .to(OrderStatusEnum.UNPAID)
                .on(OrderEventEnum.CREATE)
                .when(orderCreateCondition)
                .perform(orderCreateAction);

        builder.externalTransition()
                .from(OrderStatusEnum.UNPAID)
                .to(OrderStatusEnum.CANCELLED)
                .on(OrderEventEnum.MANUAL_CANCELLED)
                .when(orderCancelCondition)
                .perform(orderCancelAction);

        builder.externalTransition()
                .from(OrderStatusEnum.UN_RECEIVE)
                .to(OrderStatusEnum.FINISHED)
                .on(OrderEventEnum.MANUAL_CONFIRM)
                .when(orderConfirmCondition)
                .perform(orderConfirmAction);

        builder.externalTransition()
                .from(OrderStatusEnum.UN_DELIVERY)
                .to(OrderStatusEnum.WAITING_REFUND)
                .on(OrderEventEnum.UN_DELIVERY_APPLY_REFUND)
                .when(orderRefundCondition)
                .perform(orderRefundAction);

        builder.externalTransition()
                .from(OrderStatusEnum.UN_RECEIVE)
                .to(OrderStatusEnum.WAITING_REFUND)
                .on(OrderEventEnum.UN_RECEIVE_APPLY_REFUND)
                .when(orderRefundCondition)
                .perform(orderRefundAction);

        builder.externalTransition()
                .from(OrderStatusEnum.WAITING_REFUND)
                .to(OrderStatusEnum.UN_DELIVERY)
                .on(OrderEventEnum.UN_DELIVERY_REFUND_CANCEL)
                .when(orderRefundCancelCondition)
                .perform(orderRefundCancelAction);

        builder.externalTransition()
                .from(OrderStatusEnum.WAITING_REFUND)
                .to(OrderStatusEnum.UN_RECEIVE)
                .on(OrderEventEnum.UN_RECEIVE_REFUND_CANCEL)
                .when(orderRefundCancelCondition)
                .perform(orderRefundCancelAction);
        StateMachine<OrderStatusEnum,OrderEventEnum,OrderContext> build = builder.build(ORDER_STATE_MACHINE_ID);
        System.out.println(build.generatePlantUML());
        return build;
    }

}
